/*
 * Copyright (c) 2013.
 * 游戏服务器核心代码编写人陈磊拥有使用权
 * 联系方式：E-mail:13638363871@163.com ;qq:502959937
 * 个人博客主页：http://my.oschina.net/chenleijava
 */

package com.dc.gameserver.serverCore.service.battle;

import com.dc.gameserver.extComponents.utilsKit.util.random.Rnd;
import com.dc.gameserver.hardCode.PkStatus;
import com.dc.gameserver.proto.gameserverprotoVo.netCardVO;
import com.dc.gameserver.proto.gameserverprotoVo.selectLevelResponse;
import com.dc.gameserver.serverCore.model.gamemodel.LevelModel;
import com.dc.gameserver.serverCore.model.gamemodel.itemDropModel;
import com.dc.gameserver.serverCore.service.cardModule.Card;
import com.dc.gameserver.serverCore.service.cardModule.CardBox;
import com.dc.gameserver.serverCore.service.cardModule.CardBoxManager;
import com.dc.gameserver.serverCore.service.character.GameCharacter;
import com.dc.gameserver.serverCore.service.character.Monster;
import com.dc.gameserver.serverCore.service.character.PlayerInstance;
import io.netty.buffer.ByteBuf;
import javolution.util.FastTable;

/**
 * @author 石头哥哥
 *         Date: 13-11-22</br>
 *         Time: 下午2:11</br>
 *         Package: com.dc.gameserver.serverCore.service.battle</br>
 *         PVE 战斗模型 ：战斗数据组装  monster  player
 *
 *         monster:基础数据来自配置文件；
 *
 *
 *         player:扮演角色基础信息；
 *
 *
 *         注解：玩家 npc 战斗  ,点击关卡开始战斗
 *         处理  发牌逻辑
 */
public class PlayerMonsterBattle extends BaseBattle {

    private PlayerInstance player;
    private Monster monster;
    private LevelModel levelModel; // only read   关卡 model



    /**
     * 初始化player,monster战斗信息
     * 计算关卡奖励
     * @param player   战斗对象
     * @param monster  战斗对象   在游戏服务器启动的时候，战斗信息初始化完毕
     * @param levelModel  关卡model
     */
    public PlayerMonsterBattle(PlayerInstance player,Monster monster, LevelModel levelModel){
        this.player=player;
        this.monster=monster;
        this.levelModel=levelModel;


        // pve  player is first hand
        player.setFirstHand(true);
        player.setLevelModel(levelModel);

        //组装monster战斗信息
        monster.buildMonsterBattleInfo();
        //组装role战斗信息
        player.buildRoleBattleInfo(monster);

    }

    /**
     * 战斗逻辑
     */
    @Override
    public void run() throws Exception {
        CardBox cardBox= CardBoxManager.getNewCardBox();
        cardBox.setBattle(this);

        int cardBoxID=cardBox.getCardBoxID();
        player.setCardBoxID(cardBoxID);
        monster.setCardBoxID(cardBoxID);
        cardBox.getInGamePlayerList().addAll(player,monster); //游戏pk对象
        /**
         * 添加玩家到check列表，完成出牌检查做准备，每一回合结束后将会重置
         * 详见函数{@link com.dc.gameserver.serverCore.service.cardModule.CardBoxManager#resetRoundResource()}
         * PVE中，monster会永远领先于玩家出牌（前提monster不处于眩晕状态下），因而 只检测player是否出牌
         * only player
         */
        cardBox.getCheckOutCardPlayerList().addAll(player,monster);

        /**set player in PK status***/
        monster.setPkStatus(PkStatus.YES_PK);
        player.setPkStatus(PkStatus.YES_PK);
        /**初始化游戏数据牌*/
        cardBox.ClearAndIntiCardBox(player, monster);
        /**
         * 角色，怪物战斗属性推送,怪物牌数量
         */
        int levelID=levelModel.getId();
        player.DirectSend(buildBuf(player,levelID));
        player.DirectSend(buildBuf(monster,levelID));


        /** 通知出牌**/
        int round=cardBox.RoundCount();
        CardBoxManager.notifyOutCards(player,true,round);
        /**PVE战斗开始 注册回合计时器，一旦回合开始，那么该计时器就失效**/
        CardBoxManager.registerRoundOutCardTimeOutTaskAndExecutorForPVE(player);
    }

    /**
     *  角色，怪物战斗属性推送,怪物牌数量
     * @param gameCharacter
     * @return
     */
    private ByteBuf buildBuf(GameCharacter gameCharacter,int LevelID){
        selectLevelResponse.Builder  infoBuilder=selectLevelResponse.newBuilder();
        infoBuilder.setCharacterID(gameCharacter.getID());
        infoBuilder.setCurrentMagic(gameCharacter.getCurrentMagic());
        infoBuilder.setMaxMagic(gameCharacter.getMaxMagic());
        infoBuilder.setCurrentShield(gameCharacter.getCurrentShield());
        infoBuilder.setMaxShield(gameCharacter.getMaxShield());
        FastTable<Card> cardFastTable=gameCharacter.getCardlib();
        infoBuilder.setCardNum(cardFastTable.size());
        if (gameCharacter instanceof PlayerInstance){
            infoBuilder.setRoleSoul(gameCharacter.getSoul());
        }
        for (Card c:cardFastTable){
            netCardVO.Builder _cardvo=netCardVO.newBuilder();
            _cardvo.setCardNum(c.getType());   //编号
            _cardvo.setCardCount(c.getCount());  //点数
            infoBuilder.addCardList(_cardvo.build());
        }
        infoBuilder.setLevelID(LevelID); //关卡编号
        infoBuilder.setSelectLevelStatus(0x1);
        return CardBox.wrappedBufferShort(selectLevelResponse.msgID.ID_VALUE,infoBuilder.build());
    }


    /**
     * 战斗结束回调
     * 返回关卡战斗奖励物品
     * @return    int[0]:关卡编号；int[1]：掉落的物品类型编号;int[2]:掉落物品数量；int[3]：物品类型；
     * 采用转盘算法
     */
    @Override
    public int[] invokeItem(){
        int[] IDs=new int[4];
        float whichRate=Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).nextFloat();//return 0~1
        FastTable<itemDropModel> itemDropList= this.levelModel.getItemDropModelFastTable();//this list only read
        float tp=0;
        for (itemDropModel dropModel:itemDropList){
            tp=tp+dropModel.getItemRate();
        }
        //分布的概率大于1，重新划分概率
        if (tp>1){
            FastTable<RoundDesktop> roundDesktops=new FastTable<RoundDesktop>();
            for (itemDropModel dropModel:itemDropList){
                roundDesktops.addLast(new RoundDesktop(dropModel.getItemID(), dropModel.getItemRate() / tp));
            }
            float preValue=0;//迭代Rate，if whichRate<=nextValue&&>preValue;will be break;
            float nextValue=0;
            for (RoundDesktop roundDesktop:roundDesktops){
                nextValue=preValue+roundDesktop.getItemRate();
                if (whichRate>preValue&&whichRate<=nextValue){
                    IDs[0]=this.levelModel.getId();
                    IDs[1]=roundDesktop.getItemID();
                    roundDesktops.clear();   //clear  RoundDesktop object
                    roundDesktops=null;
                    //item num
                    for (itemDropModel dropModel:itemDropList){
                        if (dropModel.getItemID()==IDs[1]){
                            IDs[2]=Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).
                                    getInt(dropModel.getItemNumMin(), dropModel.getItemNumMax());
                            IDs[3]=dropModel.getItemType();//物品类型编号
                            return IDs;
                        }
                    }
                }
                preValue=nextValue;
            }
        }else{
            float preValue=0;//迭代Rate，if whichRate<=nextValue&&>preValue;will be break;
            float nextValue=0;
            for (itemDropModel model:itemDropList){
                nextValue=preValue+model.getItemRate();
                if (whichRate>preValue&&whichRate<=nextValue){
                    IDs[0]=this.levelModel.getId();
                    IDs[1]=model.getItemID();
                    //item num
                    for (itemDropModel dropModel:itemDropList){
                        if (dropModel.getItemID()==IDs[1]){
                            IDs[2]=Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).
                                    getInt(dropModel.getItemNumMin(),dropModel.getItemNumMax());
                            IDs[3]=dropModel.getItemType();//物品类型编号
                            return IDs;
                        }
                    }
                }
                preValue=nextValue;
            }
        }
        return null;
    }


    public int getLevelID(){return this.levelModel.getId();}

    public LevelModel getLevelModel(){return this.levelModel;}

    /**
     * 清理战斗对象资源
     * set null will be GC collection
     */
    @Override
    public void clearResource() {
        monster=null;
    }

    /**
     *分配权重，采用转盘算法
     */
    class RoundDesktop{
        private final int ItemID;  //物品编号
        private final float  ItemRate;//物品掉落率

        public RoundDesktop(int itemID, float itemRate) {
            ItemID = itemID;
            ItemRate = itemRate;
        }
        public int getItemID() {
            return ItemID;
        }

        public float getItemRate() {
            return ItemRate;
        }
    }


}

